/**
 * EduVerse Credentials - 去中心化身份(DID)核心实现
 * 
 * 本模块实现了与W3C DID Core v1.0兼容的去中心化身份功能，
 * 主要支持did:polygonid和did:ethr两种DID方法。
 */

// 导入模拟SDK中的常量，稍后如果可能会尝试使用真实SDK的常量
const { DidMethod, Blockchain, NetworkId } = require('../utils/sdk-mock');
console.log("从模拟SDK导入的常量:", { DidMethod, Blockchain, NetworkId });

// 尝试从真实SDK覆盖常量，如果可用
let realSDKConstants = {};
try {
  const polygonIdSdk = require('@0xpolygonid/js-sdk');
  realSDKConstants = {
    DidMethod: polygonIdSdk.DidMethod,
    Blockchain: polygonIdSdk.Blockchain,
    NetworkId: polygonIdSdk.NetworkId
  };
  console.log("从真实SDK导入的常量可用");
  
  // 如果成功导入真实常量，使用它们覆盖模拟常量
  if (realSDKConstants.DidMethod && realSDKConstants.Blockchain && realSDKConstants.NetworkId) {
    Object.assign({ DidMethod, Blockchain, NetworkId }, realSDKConstants);
    console.log("使用真实SDK常量");
  }
} catch (error) {
  console.log("无法加载真实SDK常量，继续使用模拟常量:", error.message);
}

const { v4: uuidv4 } = require('uuid');
const { ethers } = require('ethers');
let IdentityWallet, Resolver, ethrDid;

// 尝试导入其他依赖
try {
  const sdkPackage = require('@0xpolygonid/js-sdk');
  IdentityWallet = sdkPackage.IdentityWallet;
  Resolver = require('did-resolver').Resolver;
  ethrDid = require('ethr-did-resolver');
} catch (error) {
  console.log("部分模块导入失败，某些功能可能受限:", error.message);
  // 提供模拟或空对象以避免null引用错误
  IdentityWallet = class {};
  Resolver = class {};
  ethrDid = { getResolver: () => ({}) };
}

/**
 * 获取DID的字符串表示
 * 
 * @param {Object|string} did - DID对象或DID字符串
 * @returns {string} DID字符串表示
 */
function didToString(did) {
  if (typeof did === 'string') {
    return did;
  } else if (did && typeof did.string === 'function') {
    return did.string();
  } else if (did && did.id) {
    return did.id;
  } else if (did && typeof did === 'object') {
    // 尝试构建一个DID字符串
    return `did:${did.method || 'mock'}:${did.blockchain || 'local'}:${did.networkId || 'test'}:${did.identifier || Date.now()}`;
  }
  return `did:mock:${Date.now()}`;
}

/**
 * 创建一个did:polygonid身份
 * 
 * @param {Object} identityWallet - 已初始化的IdentityWallet实例
 * @param {Object} opts - 身份创建选项
 * @returns {Promise<Object>} 包含DID和认证凭证的对象
 */
async function createPolygonIdIdentity(identityWallet, opts = {}) {
  console.log("创建Polygon ID身份...");
  console.log("使用的DidMethod:", DidMethod);
  console.log("使用的Blockchain:", Blockchain);
  console.log("使用的NetworkId:", NetworkId);

  const creationOpts = {
    method: DidMethod.PolygonId,
    blockchain: Blockchain.Polygon,
    networkId: NetworkId.Amoy,
    revocationOpts: {
      id: "urn:uuid:" + uuidv4(),
      type: "Iden3ReverseSparseMerkleTreeProof",
      nonce: 0
    },
    ...opts
  };

  console.log("创建did:polygonid身份，参数:", creationOpts);
  
  try {
    const { did, credential: authCredential } = await identityWallet.createIdentity(creationOpts);
    const didString = didToString(did);
    console.log(`Created DID: ${didString}`);
    return { did, authCredential, didString };
  } catch (error) {
    console.error("创建身份时出错:", error);
    throw error;
  }
}

/**
 * 发布did:polygonid身份状态到链上
 * 
 * @param {Object} identityWallet - IdentityWallet实例
 * @param {Object} proofService - ProofService实例
 * @param {Object} did - DID对象
 * @param {Object} dataStorage - 数据存储实例
 * @param {Object} ethSigner - 以太坊签名者对象
 * @param {string} rhsUrl - RHS服务URL
 * @returns {Promise<Object>} 交易结果
 */
async function publishPolygonIdState(identityWallet, proofService, did, dataStorage, ethSigner, rhsUrl) {
  console.log("Publishing state for:", didToString(did));
  
  if (rhsUrl) {
    console.log("Publishing state to RHS:", rhsUrl);
    await identityWallet.publishStateToRHS(did, rhsUrl);
  }
  
  const oldTreeState = {
    // 依据SDK的结构填充
  };
  
  console.log("Publishing state to blockchain...");
  const txResult = await proofService.transitState(did, oldTreeState, true, dataStorage.states, ethSigner);
  console.log("State published on-chain. Transaction hash:", txResult.hash);
  
  return txResult;
}

/**
 * 创建一个did:ethr身份
 * 
 * @param {string} network - 网络标识符，如"amoy"
 * @param {Object} opts - 创建选项，包括是否使用已有账户
 * @returns {Promise<Object>} 包含DID和私钥的对象
 */
async function createEthrIdentity(network = "amoy", opts = {}) {
  let wallet;
  
  if (opts.privateKey) {
    wallet = new ethers.Wallet(opts.privateKey);
  } else {
    wallet = ethers.Wallet.createRandom();
  }
  
  const address = await wallet.getAddress();
  const did = `did:ethr:${network}:${address}`;
  
  console.log(`Created did:ethr identity: ${did}`);
  
  return {
    did,
    privateKey: wallet.privateKey,
    address
  };
}

/**
 * 创建DID解析器实例
 * 
 * @param {Object} config - 解析器配置
 * @returns {Object} DID解析器实例
 */
function createDIDResolver(config = {}) {
  const { networks = ["amoy"], rpcUrl } = config;
  
  // 配置ethr-did解析器
  const ethrResolverConfig = {};
  
  networks.forEach(network => {
    ethrResolverConfig[network] = { rpcUrl };
  });
  
  const ethrResolver = ethrDid.getResolver(ethrResolverConfig);
  
  // 创建通用解析器
  return new Resolver(ethrResolver);
}

/**
 * 解析DID文档
 * 
 * @param {string} did - 要解析的DID标识符
 * @param {Object} resolver - DID解析器实例
 * @returns {Promise<Object>} DID文档
 */
async function resolveDID(did, resolver) {
  try {
    console.log(`Resolving DID: ${didToString(did)}`);
    const didDocument = await resolver.resolve(didToString(did));
    return didDocument;
  } catch (error) {
    console.error(`Error resolving DID ${didToString(did)}:`, error);
    throw error;
  }
}

module.exports = {
  createPolygonIdIdentity,
  publishPolygonIdState,
  createEthrIdentity,
  createDIDResolver,
  resolveDID,
  didToString,
  // 导出常量以便其他模块使用
  DidMethod,
  Blockchain,
  NetworkId
}; 